/**
 * Created by lizi on 2017/4/17.
 */
(function () {

// Inspired by http://informationandvisualization.de/blog/box-plot
    var i, j, node;
    var groupSep = 10;

    var nodeRadius = d3.scaleSqrt().range([3, 7]);

    var linkWidth = d3.scaleLinear().range([1.5, 2 * nodeRadius.range()[0]]);

    var margin = {
        top: nodeRadius.range()[1] + 1,
        right: nodeRadius.range()[1] + 1,
        bottom: nodeRadius.range()[1] + 1,
        left: nodeRadius.range()[1] + 1
    };

    var width = 960 - margin.left - margin.right;
    var height = 400 - margin.top - margin.bottom;

    var x = d3.scaleLinear().range([0, width]);

    var svg = d3.select('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    d3.json('./json/jean.json', function (error, graph) {
        if (error) throw error;

        var idToNode = {};

        graph.nodes.forEach(function (n) {
            idToNode[n.id] = n;
        });

        graph.links.forEach(function (e) {
            e.source = idToNode[e.source];
            e.target = idToNode[e.target];
        });

        // Sort nodes by first appearance (volume, book, chapter)
        graph.nodes.forEach(function (n) {
            n.chapters = n.chapters.map(function (chaps) {
                return chaps.split('.').map(function (c) {
                    return parseInt(c);
                });
            });
            n.chapters.sort(chapterCompare).reverse();
            n.firstChapter = n.chapters[0];
        });
        graph.nodes.sort(function (a, b) {
            return chapterCompare(a.firstChapter, b.firstChapter);
        }).reverse();

        // Compute x,y coordinates (have a little extra separation when we switch volumes)
        for (i = 0, j = 0; i < graph.nodes.length; ++i) {
            node = graph.nodes[i];
            if (i > 0 && graph.nodes[i - 1].firstChapter[0] != node.firstChapter[0]) ++j;
            node.x = j * groupSep + i * (width - 4 * groupSep) / (graph.nodes.length - 1);
            node.y = height;
        }

        nodeRadius.domain(d3.extent(graph.nodes, function (d) {
            return d.chapters.length;
        }));

        linkWidth.domain(d3.extent(graph.links, function (d) {
            return d.chapters.length;
        }));

        var link = svg.append('g')
            .attr('class', 'links')
            .selectAll('path')
            .data(graph.links)
            .enter().append('path')
            .attr('d', function (d) {
                return ['M', d.source.x, height, 'A',
                    (d.source.x - d.target.x) / 2, ',',
                    (d.source.x - d.target.x) / 2, 0, 0, ',',
                    d.source.x < d.target.x ? 1 : 0, d.target.x, ',', height]
                    .join(' ');
            })
            .attr('stroke-width', function (d) {
                return linkWidth(d.chapters.length);
            })
            .on('mouseover', function (d) {
                link.style('stroke', null);
                d3.select(this).style('stroke', '#d62333');
                node.style('fill', function (node_d) {
                    return node_d === d.source || node_d === d.target ? 'black' : null;
                });
            })
            .on('mouseout', function (d) {
                link.style('stroke', null);
                node.style('fill', null);
            });

        var node = svg.append('g')
            .attr('class', 'nodes')
            .selectAll('circle')
            .data(graph.nodes)
            .enter().append('circle')
            .attr('cx', function (d) {
                return d.x;
            })
            .attr('cy', function (d) {
                return d.y;
            })
            .attr('r', function (d) {
                return nodeRadius(d.chapters.length);
            })
            .on('mouseover', function (d) {
                node.style('fill', null);
                d3.select(this).style('fill', 'black');
                var nodesToHighlight = graph.links.map(function (e) {
                    return e.source === d ? e.target : e.target === d ? e.source : 0
                })
                    .filter(function (d) {
                        return d;
                    });
                node.filter(function (d) {
                    return nodesToHighlight.indexOf(d) >= 0;
                })
                    .style('fill', '#555');
                link.style('stroke', function (link_d) {
                    return link_d.source === d | link_d.target === d ? '#d62333' : null;
                });
            })
            .on('mouseout', function (d) {
                node.style('fill', null);
                link.style('stroke', null);
            });

        node.append('title').text(function (d) {
            return d.name + ' - ' + d.firstChapter.join('.');
        });

        function chapterCompare(aChaps, bChaps) {
            if (aChaps[0] != bChaps[0])
                return bChaps[0] - aChaps[0];
            else if (aChaps[1] != bChaps[0])
                return bChaps[1] - aChaps[1];
            else if (aChaps[2] != bChaps[2])
                return bChaps[2] - aChaps[2];
            return 0;
        }
    });

})();